﻿
using System;

namespace Framework
{
    public static class EnumExtension
    {
        public static string AsDescription(this Enum e)
        {
            return EnumUtil.GetDescription(e);
        }

        /// <summary>
        /// Determines whether the Enum has Flag. For Flag style Enumerated types.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type">The type.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        /// 	<c>true</c> if [has] [the specified type]; otherwise, <c>false</c>.
        /// </returns>
        public static bool EnumHas<T>(this Enum type, T value)
        {
            try
            {
                // Note: If this is failing then it could be cause you have started your flags off from zero base
                // Note: Zero can be reserved for NONE, but it should not be used by a on flag
                return (((int)(object)type & (int)(object)value) == (int)(object)value);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Determines whether the Enum is Flag only. For Flag style Enumerated types.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type">The type.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        /// 	<c>true</c> if [is] [the specified type]; otherwise, <c>false</c>.
        /// </returns>
        public static bool EnumIs<T>(this Enum type, T value)
        {
            try
            {
                return (int)(object)type == (int)(object)value;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Adds a Flag to Enum. For Flag style Enumerated types.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type">The type.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static T EnumAdd<T>(this Enum type, T value)
        {
            try
            {
                return (T)(object)(((int)(object)type | (int)(object)value));
            }
            catch (Exception ex)
            {
                throw new ArgumentException(
                    string.Format("Could not append value from enumerated type '{0}'.", typeof(T).Name), ex);
            }
        }

        /// <summary>
        /// Removes a Flag from Enum. For Flag style Enumerated types.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type">The type.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static T EnumRemove<T>(this Enum type, T value)
        {
            try
            {
                return (T)(object)(((int)(object)type & ~(int)(object)value));
            }
            catch (Exception ex)
            {
                throw new ArgumentException(
                    string.Format("Could not remove value from enumerated type '{0}'.", typeof(T).Name), ex);
            }
        }

    }
}